Compare commits

..

3 Commits

Author SHA1 Message Date
Alex Forencich
0f09b8bdaa cndm: Add register access command
Signed-off-by: Alex Forencich <alex@alexforencich.com>
2026-03-02 00:33:31 -08:00
Alex Forencich
a3ef71ae87 cndm: Fix testbench command structs
Signed-off-by: Alex Forencich <alex@alexforencich.com>
2026-03-01 23:33:51 -08:00
Alex Forencich
499a70982f prim: Fix single-clock TDP RAM inference
Signed-off-by: Alex Forencich <alex@alexforencich.com>
2026-03-01 20:43:13 -08:00
6 changed files with 119 additions and 5 deletions

View File

@@ -144,6 +144,7 @@ struct cndm_priv {
// cndm_cmd.c // cndm_cmd.c
int cndm_exec_mbox_cmd(struct cndm_dev *cdev, void *cmd, void *rsp); int cndm_exec_mbox_cmd(struct cndm_dev *cdev, void *cmd, void *rsp);
int cndm_exec_cmd(struct cndm_dev *cdev, void *cmd, void *rsp); int cndm_exec_cmd(struct cndm_dev *cdev, void *cmd, void *rsp);
int cndm_access_reg(struct cndm_dev *cdev, u32 reg, int raw, int write, u64 *data);
// cndm_devlink.c // cndm_devlink.c
struct devlink *cndm_devlink_alloc(struct device *dev); struct devlink *cndm_devlink_alloc(struct device *dev);

View File

@@ -45,3 +45,32 @@ int cndm_exec_cmd(struct cndm_dev *cdev, void *cmd, void *rsp)
{ {
return cndm_exec_mbox_cmd(cdev, cmd, rsp); return cndm_exec_mbox_cmd(cdev, cmd, rsp);
} }
int cndm_access_reg(struct cndm_dev *cdev, u32 reg, int raw, int write, u64 *data)
{
struct cndm_cmd cmd;
struct cndm_cmd rsp;
cmd.opcode = CNDM_CMD_OP_ACCESS_REG;
cmd.flags = 0x00000000;
cmd.port = 0;
cmd.qn = 0;
cmd.qn2 = 0;
cmd.pd = 0;
cmd.size = 0;
cmd.dboffs = reg;
cmd.ptr1 = *data;
cmd.ptr2 = 0;
if (write)
cmd.flags |= 0x00000001;
if (raw)
cmd.flags |= 0x00000100;
cndm_exec_cmd(cdev, &cmd, &rsp);
if (!write)
*data = rsp.ptr2;
return 0;
}

View File

@@ -15,6 +15,8 @@ Authors:
#define CNDM_CMD_OP_NOP 0x0000 #define CNDM_CMD_OP_NOP 0x0000
#define CNDM_CMD_OP_ACCESS_REG 0x0180
#define CNDM_CMD_OP_CREATE_EQ 0x0200 #define CNDM_CMD_OP_CREATE_EQ 0x0200
#define CNDM_CMD_OP_MODIFY_EQ 0x0201 #define CNDM_CMD_OP_MODIFY_EQ 0x0201
#define CNDM_CMD_OP_QUERY_EQ 0x0202 #define CNDM_CMD_OP_QUERY_EQ 0x0202

View File

@@ -44,6 +44,8 @@ localparam DP_APB_STRB_W = m_apb_dp_ctrl.STRB_W;
typedef enum logic [15:0] { typedef enum logic [15:0] {
CMD_OP_NOP = 16'h0000, CMD_OP_NOP = 16'h0000,
CMD_OP_ACCESS_REG = 16'h0180,
CMD_OP_CREATE_EQ = 16'h0200, CMD_OP_CREATE_EQ = 16'h0200,
CMD_OP_MODIFY_EQ = 16'h0201, CMD_OP_MODIFY_EQ = 16'h0201,
CMD_OP_QUERY_EQ = 16'h0202, CMD_OP_QUERY_EQ = 16'h0202,
@@ -73,6 +75,9 @@ typedef enum logic [15:0] {
typedef enum logic [4:0] { typedef enum logic [4:0] {
STATE_IDLE, STATE_IDLE,
STATE_START, STATE_START,
STATE_REG_1,
STATE_REG_2,
STATE_REG_3,
STATE_Q_RESET_1, STATE_Q_RESET_1,
STATE_Q_RESET_2, STATE_Q_RESET_2,
STATE_Q_SET_BASE_L, STATE_Q_SET_BASE_L,
@@ -259,7 +264,7 @@ always_comb begin
endcase endcase
case (opcode_reg) case (opcode_reg)
16'h0000: begin CMD_OP_NOP: begin
// NOP // NOP
m_axis_rsp_tdata_next = '0; // TODO m_axis_rsp_tdata_next = '0; // TODO
m_axis_rsp_tvalid_next = 1'b1; m_axis_rsp_tvalid_next = 1'b1;
@@ -267,6 +272,10 @@ always_comb begin
state_next = STATE_SEND_RSP; state_next = STATE_SEND_RSP;
end end
CMD_OP_ACCESS_REG: begin
// access register
state_next = STATE_REG_1;
end
CMD_OP_CREATE_EQ, CMD_OP_CREATE_EQ,
CMD_OP_CREATE_CQ, CMD_OP_CREATE_CQ,
CMD_OP_CREATE_SQ, CMD_OP_CREATE_SQ,
@@ -321,6 +330,48 @@ always_comb begin
end end
endcase endcase
end end
STATE_REG_1: begin
// register access 1
cmd_ram_rd_addr = 7;
if (!m_apb_dp_ctrl_psel_reg) begin
m_apb_dp_ctrl_paddr_next = DP_APB_ADDR_W'(cmd_ram_rd_data);
state_next = STATE_REG_2;
end else begin
state_next = STATE_REG_1;
end
end
STATE_REG_2: begin
// register access 2
cmd_ram_rd_addr = 8;
if (!m_apb_dp_ctrl_psel_reg) begin
m_apb_dp_ctrl_psel_next = 1'b1;
m_apb_dp_ctrl_pwrite_next = flags_reg[0];
m_apb_dp_ctrl_pwdata_next = cmd_ram_rd_data;
m_apb_dp_ctrl_pstrb_next = '1;
state_next = STATE_REG_3;
end else begin
state_next = STATE_REG_2;
end
end
STATE_REG_3: begin
// register access 3
cmd_ram_wr_data = m_apb_dp_ctrl.prdata;
cmd_ram_wr_addr = 10;
cmd_ram_wr_en = 1'b1;
if (m_apb_dp_ctrl.pready) begin
m_axis_rsp_tdata_next = '0; // TODO
m_axis_rsp_tvalid_next = 1'b1;
m_axis_rsp_tlast_next = 1'b0;
state_next = STATE_SEND_RSP;
end else begin
state_next = STATE_REG_3;
end
end
STATE_Q_RESET_1: begin STATE_Q_RESET_1: begin
// reset queue 1 // reset queue 1
if (!m_apb_dp_ctrl_psel_reg) begin if (!m_apb_dp_ctrl_psel_reg) begin

View File

@@ -19,6 +19,8 @@ from cocotb.queue import Queue
# Command opcodes # Command opcodes
CNDM_CMD_OP_NOP = 0x0000 CNDM_CMD_OP_NOP = 0x0000
CNDM_CMD_OP_ACCESS_REG = 0x0180
CNDM_CMD_OP_CREATE_EQ = 0x0200 CNDM_CMD_OP_CREATE_EQ = 0x0200
CNDM_CMD_OP_MODIFY_EQ = 0x0201 CNDM_CMD_OP_MODIFY_EQ = 0x0201
CNDM_CMD_OP_QUERY_EQ = 0x0202 CNDM_CMD_OP_QUERY_EQ = 0x0202
@@ -97,7 +99,7 @@ class Port:
self.rxcq = self.driver.pool.alloc_region(self.rxcq_size*16) self.rxcq = self.driver.pool.alloc_region(self.rxcq_size*16)
addr = self.rxcq.get_absolute_address(0) addr = self.rxcq.get_absolute_address(0)
rsp = await self.driver.exec_cmd(struct.pack("<HHLLLLLLLLLLLLL", rsp = await self.driver.exec_cmd(struct.pack("<HHLLLLLLLQQLLLL",
0, # rsvd 0, # rsvd
CNDM_CMD_OP_CREATE_CQ, # opcode CNDM_CMD_OP_CREATE_CQ, # opcode
0x00000000, # flags 0x00000000, # flags
@@ -119,7 +121,7 @@ class Port:
self.rxq = self.driver.pool.alloc_region(self.rxq_size*16) self.rxq = self.driver.pool.alloc_region(self.rxq_size*16)
addr = self.rxq.get_absolute_address(0) addr = self.rxq.get_absolute_address(0)
rsp = await self.driver.exec_cmd(struct.pack("<HHLLLLLLLLLLLLL", rsp = await self.driver.exec_cmd(struct.pack("<HHLLLLLLLQQLLLL",
0, # rsvd 0, # rsvd
CNDM_CMD_OP_CREATE_RQ, # opcode CNDM_CMD_OP_CREATE_RQ, # opcode
0x00000000, # flags 0x00000000, # flags
@@ -143,7 +145,7 @@ class Port:
self.txcq = self.driver.pool.alloc_region(self.txcq_size*16) self.txcq = self.driver.pool.alloc_region(self.txcq_size*16)
addr = self.txcq.get_absolute_address(0) addr = self.txcq.get_absolute_address(0)
rsp = await self.driver.exec_cmd(struct.pack("<HHLLLLLLLLLLLLL", rsp = await self.driver.exec_cmd(struct.pack("<HHLLLLLLLQQLLLL",
0, # rsvd 0, # rsvd
CNDM_CMD_OP_CREATE_CQ, # opcode CNDM_CMD_OP_CREATE_CQ, # opcode
0x00000000, # flags 0x00000000, # flags
@@ -165,7 +167,7 @@ class Port:
self.txq = self.driver.pool.alloc_region(self.txq_size*16) self.txq = self.driver.pool.alloc_region(self.txq_size*16)
addr = self.txq.get_absolute_address(0) addr = self.txq.get_absolute_address(0)
rsp = await self.driver.exec_cmd(struct.pack("<HHLLLLLLLLLLLLL", rsp = await self.driver.exec_cmd(struct.pack("<HHLLLLLLLQQLLLL",
0, # rsvd 0, # rsvd
CNDM_CMD_OP_CREATE_SQ, # opcode CNDM_CMD_OP_CREATE_SQ, # opcode
0x00000000, # flags 0x00000000, # flags
@@ -360,6 +362,33 @@ class Driver:
self.ports.append(port) self.ports.append(port)
async def access_reg(self, reg, raw, write=False, data=0):
flags = 0
if raw:
flags |= 0x00000100
if write:
flags |= 0x00000001
rsp = await self.exec_cmd(struct.pack("<HHLLLLLLLQQLLLL",
0, # rsvd
CNDM_CMD_OP_ACCESS_REG, # opcode
flags, # flags
0, # port
0, # sqn
0, # cqn
0, # pd
0, # size
reg, # dboffs
data, # base addr
0, # ptr2
0, # prod_ptr
0, # cons_ptr
0, # rsvd
0, # rsvd
))
return struct.unpack_from("<Q", rsp, 10*4)[0]
async def exec_cmd(self, cmd): async def exec_cmd(self, cmd):
return await self.exec_mbox_cmd(cmd) return await self.exec_mbox_cmd(cmd)

View File

@@ -74,7 +74,9 @@ always_ff @(posedge clk) begin
a_rd_data_reg <= mem[a_addr]; a_rd_data_reg <= mem[a_addr];
end end
end end
end
always_ff @(posedge clk) begin
if (b_en) begin if (b_en) begin
if (b_wr_en) begin if (b_wr_en) begin
if (STRB_EN) begin if (STRB_EN) begin