mirror of
https://github.com/MPSU/APS.git
synced 2025-09-15 17:20:10 +00:00
ЛР15. Добавление тб для таймера
This commit is contained in:
@@ -53,7 +53,7 @@
|
||||
|0x00 | R | [0:2⁶⁴-1] | Значение системного счетчика, доступное только для чтения |
|
||||
|0x04 | RW | [0:2⁶⁴-1] | Указание задержки, спустя которую таймер будет генерировать прерывание |
|
||||
|0x08 | RW | [0:2] | Указание режима генерации прерываний (выключен, заданное число раз, бесконечно) |
|
||||
|0x0c | RW | [0:2³²] | Указание количества повторений генерации прерываний |
|
||||
|0x0c | RW | [0:2³²-1] | Указание количества повторений генерации прерываний |
|
||||
|0x24 | W | 1 | Программный сброс |
|
||||
|
||||
Прототип модуля следующий:
|
||||
@@ -265,25 +265,26 @@ Correct operation validated. See README.md for run and reporting rules.
|
||||
## Порядок выполнения задания
|
||||
|
||||
1. [Опишите](#таймер) таймер в виде модуля `timer_sb_ctrl`.
|
||||
2. Подключите данный модуль к системной шине. Сигнал прерывания этого модуля подключать не нужно.
|
||||
2. Проверьте описанный модуль с помощью модуля [tb_timer](tb_timer.sv).
|
||||
3. Подключите `timer_sb_ctrl` к системной шине. Сигнал прерывания этого модуля подключать не нужно.
|
||||
2.1 В случае, если до этого в ЛР12 вашим устройством вывода было не UART TX, вам необходимо подключить к системной шине и готовый модуль [uart_tx_sb_ctrl](../Made-up%20modules/lab_12.uart_tx_sb_ctrl.sv).
|
||||
3. Получите исходники программы Coremark. Для этого можно либо склонировать репозиторий, либо скачать его в виде архива со страницы: [https://github.com/eembc/coremark](https://github.com/eembc/coremark).
|
||||
4. Добавьте реализацию платформозависимых функций программы coremark. Для этого в папке `barebones` необходимо:
|
||||
4. Получите исходники программы Coremark. Для этого можно либо склонировать репозиторий, либо скачать его в виде архива со страницы: [https://github.com/eembc/coremark](https://github.com/eembc/coremark).
|
||||
5. Добавьте реализацию платформозависимых функций программы coremark. Для этого в папке `barebones` необходимо:
|
||||
1. в файле `core_portme.c`:
|
||||
1. [реализовать](#реализация-функции-измеряющей-время) функцию `barebones_clock`, возвращающую текущее значение системного счетчика;
|
||||
2. объявить макрос `CLOCKS_PER_SEC`, характеризующий тактовую частоту процессора;
|
||||
3. [реализовать](#реализация-функции-первичной-настройки) функцию `portable_init`, выполняющую первичную инициализацию периферийных устройств до начала теста;
|
||||
2. в файле `ee_printf.c` [реализовать](#реализация-вывода-очередного-символа-сообщения) функцию `uart_send_char`, отвечающую за отправку очередного символа сообщения о результате.
|
||||
5. Добавьте с заменой в корень программы файлы [Makefile](Makefile), [linker_script.ld](linker_script.ld) и [startup.S](../13.%20Programming/startup.S).
|
||||
6. Скомпилируйте программу вызовом `make`.
|
||||
6. Добавьте с заменой в корень программы файлы [Makefile](Makefile), [linker_script.ld](linker_script.ld) и [startup.S](../13.%20Programming/startup.S).
|
||||
7. Скомпилируйте программу вызовом `make`.
|
||||
1. Если кросскомпилятор расположен не в директории `C:/riscv_cc`, перед вызовом `make` вам необходимо соответствующим образом отредактировать первую строчку в `Makefile`.
|
||||
2. В случае отсутствия на компьютере утилиты `make`, вы можете самостоятельно скомпилировать программу вызовом команд, представленных в разделе ["Компиляция"](#компиляция).
|
||||
7. Временно измените размер памяти инструкций до 64KiB.
|
||||
8. Временно измените размер памяти инструкций до 64KiB.
|
||||
1. Для этого необходимо изменить размер памяти инструкций с 1024 слов до 16384 слов.
|
||||
2. Кроме того, необходимо изменить используемые индексы адреса с `[11:2]` на `[15:2]`.
|
||||
8. Проинициализируйте память инструкций и память данных файлами "coremark_instr.mem" и "coremark_data.mem", полученными в ходе компиляции программы.
|
||||
9. Выполните моделирование системы с помощью модуля [tb_coremark](tb_coremark).
|
||||
1. Результаты теста будут выведены приблизительно на `335ms` времени моделирования.
|
||||
9. Проинициализируйте память инструкций и память данных файлами "coremark_instr.mem" и "coremark_data.mem", полученными в ходе компиляции программы.
|
||||
10. Выполните моделирование системы с помощью модуля [tb_coremark](tb_coremark).
|
||||
1. Результаты теста будут выведены приблизительно на `335ms` времени моделирования.
|
||||
|
||||
<details>
|
||||
<summary>10. Прочти меня после успешного завершения моделирования </summary>
|
||||
@@ -318,7 +319,7 @@ Iterations/Sec : <скрыто то получения результатов
|
||||
|
||||
Это и есть так называемый "кормарк" — метрика данной программы. Результат нашего процессора: 3.88 кормарка.
|
||||
|
||||
Обычно, для сравнения между собой нескольких реализаций микроархитектур, более достоверной считается величина "кормарк / МГц", т.е. значение кормарка поделеное на тактовую частоту процессора. Дело в том, что можно реализовать какую-нибудь очень сложную архитектуру, которая будет выдавать очень хороший кормарк, но при этом будет иметь очень низкую частоту. Более того, при сравнении с другими результатами, необходимо учитывать флаги оптимизации, которые использовались при компиляции программы, поскольку они также влияют на результат.
|
||||
Обычно, для сравнения между собой нескольких реализаций микроархитектур, более достоверной считается величина "кормарк / МГц", т.е. значение кормарка, поделеное на тактовую частоту процессора. Дело в том, что можно реализовать какую-нибудь очень сложную архитектуру, которая будет выдавать очень хороший кормарк, но при этом будет иметь очень низкую частоту. Более того, при сравнении с другими результатами, необходимо учитывать флаги оптимизации, которые использовались при компиляции программы, поскольку они также влияют на результат.
|
||||
|
||||
Мы не будем уходить в дебри темных паттернов маркетинга и вместо этого будет оценивать производительность в лоб: сколько кормарков в секунду смог прогнать наш проц в сравнении с представленными результатами других систем вне зависимости от их оптимизаций.
|
||||
|
||||
|
95
Labs/15. Coremark/tb_timer.sv
Normal file
95
Labs/15. Coremark/tb_timer.sv
Normal file
@@ -0,0 +1,95 @@
|
||||
module tb_timer();
|
||||
|
||||
logic clk_i;
|
||||
logic rst_i;
|
||||
logic req_i;
|
||||
logic write_enable_i;
|
||||
logic [31:0] addr_i;
|
||||
logic [31:0] write_data_i;
|
||||
logic [31:0] read_data_o;
|
||||
logic ready_o;
|
||||
logic interrupt_request_o;
|
||||
|
||||
localparam SYS_CNT_ADDR = 32'h0000_0000;
|
||||
localparam DELAY_ADDR = 32'h0000_0004;
|
||||
localparam MODE_ADDR = 32'h0000_0008;
|
||||
localparam REP_CNT_ADDR = 32'h0000_000C;
|
||||
localparam RST_ADDR = 32'h0000_0024;
|
||||
|
||||
localparam OFF = 32'd0;
|
||||
localparam NTIMES = 32'd1;
|
||||
localparam FOREVER = 32'd2;
|
||||
|
||||
always #50ns clk_i = !clk_i;
|
||||
|
||||
timer_sb_ctrl DUT(.*);
|
||||
|
||||
initial begin
|
||||
clk_i = 0;
|
||||
rst_i = 0;
|
||||
req_i = 0;
|
||||
write_enable_i = 0;
|
||||
addr_i = 0;
|
||||
write_data_i = 0;
|
||||
@(posedge clk_i);
|
||||
rst_i = 1;
|
||||
repeat(5) @(posedge clk_i);
|
||||
rst_i = 0;
|
||||
|
||||
test_ntimes(0, 0);
|
||||
test_ntimes(0, 1);
|
||||
test_ntimes(1, 0);
|
||||
test_ntimes(1, 1);
|
||||
test_ntimes(10, 1);
|
||||
test_ntimes(10, 10);
|
||||
test_forever(10);
|
||||
write_req(MODE_ADDR, OFF);
|
||||
test_ntimes(10, 10);
|
||||
test_forever(10);
|
||||
test_ntimes(10, 10);
|
||||
$finish();
|
||||
end
|
||||
|
||||
one_cycle_irq: assert property (
|
||||
@(posedge clk_i) disable iff ( rst_i || (DUT.delay==32'd1))
|
||||
(interrupt_request_o |=> !interrupt_request_o)
|
||||
);
|
||||
|
||||
task test_ntimes(input logic [31:0] delay, ntimes);
|
||||
write_req(DELAY_ADDR, delay);
|
||||
write_req(REP_CNT_ADDR, ntimes);
|
||||
write_req(MODE_ADDR, NTIMES);
|
||||
repeat(ntimes) begin
|
||||
repeat(delay)@(posedge clk_i);
|
||||
if(!interrupt_request_o & delay) begin
|
||||
$error("test_ntimes: delay = %d, ntimes = %d", delay, ntimes);
|
||||
end
|
||||
end
|
||||
endtask
|
||||
|
||||
task test_forever(input logic [31:0] delay);
|
||||
write_req(DELAY_ADDR, delay);
|
||||
write_req(MODE_ADDR, FOREVER);
|
||||
repeat(1000) begin
|
||||
repeat(delay) @(posedge clk_i);
|
||||
if(!interrupt_request_o) begin
|
||||
$error("test_forever");
|
||||
end
|
||||
end
|
||||
endtask
|
||||
|
||||
task write_req(input [31:0] addr, data);
|
||||
@(posedge clk_i);
|
||||
addr_i <= addr;
|
||||
write_data_i <= data;
|
||||
write_enable_i <= 1'b1;
|
||||
req_i <= 1'b1;
|
||||
@(posedge clk_i);
|
||||
while(!ready_o) begin
|
||||
@(posedge clk_i);
|
||||
end
|
||||
req_i <= 1'b0;
|
||||
write_enable_i <= 1'b0;
|
||||
endtask
|
||||
|
||||
endmodule
|
Reference in New Issue
Block a user