Skip to content

Commit

Permalink
multiaddr_decode: Add default port logic
Browse files Browse the repository at this point in the history
  • Loading branch information
colluca committed Sep 12, 2024
1 parent 10dac0f commit 0fd2ba3
Showing 1 changed file with 71 additions and 11 deletions.
82 changes: 71 additions & 11 deletions src/multiaddr_decode.sv
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@
/// is set.
/// For each rule, it also returns the subset of addresses in {`addr_i`, `mask_i`} which
/// match the rule {`addr_o[i]`, `mask_o[i]`}.
///
/// There is the possibility to add a default mapping:
/// `en_default_idx_i`: Driving this port to `1'b1` maps all input addresses
/// for which no rule in `addr_map_i` exists to the default index specified by
/// `default_idx_i`. In this case, `dec_error_o` is always `1'b0`.
/// Note: `default_idx_i` must carry the rule representing the union of all other
/// rules' address sets, in order to determine if any address in the input address
/// doesn't fall in the address set of any rule.
module multiaddr_decode #(
/// Highest index which can happen in a rule.
parameter int unsigned NoIndices = 32'd0,
Expand Down Expand Up @@ -60,7 +68,16 @@ module multiaddr_decode #(
/// to the {addr, mask} representation (and viceversa) using the following equations:
/// - mask = {'0, {log2(end - start){1'b1}}}
/// - addr = start
parameter type rule_t = logic
parameter type rule_t = logic,
/// Dependent parameter, do **not** overwite!
///
/// Width of the `default_idx_i` input port.
parameter int unsigned IdxWidth = cf_math_pkg::idx_width(NoIndices),
/// Dependent parameter, do **not** overwite!
///
/// Type of the `default_idx_i` input port.
parameter type idx_t = logic [IdxWidth-1:0]

) (
/// Multi-address to decode.
input addr_t addr_i,
Expand All @@ -75,19 +92,35 @@ module multiaddr_decode #(
/// Decode is valid.
output logic dec_valid_o,
/// Decode is not valid, no matching rule found.
output logic dec_error_o
output logic dec_error_o,
/// Enable default port mapping.
///
/// When not used, tie to `0`.
input logic en_default_idx_i,
/// Default port rule.
///
/// When `en_default_idx_i` is `1`, this containes the index when the input doesn't
/// fully match the other rules. To easily determine if this is the case, this signal
/// carries the rule representing the union of all other rules. This is not the default
/// slave's rule but actually its complement.
///
/// When not used, tie to `0`.
input rule_t default_idx_i
);

logic [NoRules-1:0] matched_rules; // purely for address map debugging

always_comb begin
// default assignments
matched_rules = '0;
dec_valid_o = 1'b0;
dec_error_o = 1'b1;
select_o = '0;
addr_o = '0;
mask_o = '0;
matched_rules = '0;
dec_valid_o = 1'b0;
dec_error_o = en_default_idx_i ? 1'b0 : 1'b1;
select_o = '0;
// input address and mask are propagated unchanged to the default slave
addr_o = '0;
mask_o = '0;
addr_o[default_idx_i.idx] = en_default_idx_i ? addr_i : '0;
mask_o[default_idx_i.idx] = en_default_idx_i ? mask_i : '0;

// Match the rules
for (int unsigned i = 0; i < NoRules; i++) begin
Expand Down Expand Up @@ -117,6 +150,14 @@ module multiaddr_decode #(
addr_o[idx] = (~mask_i & addr_i) | (mask_i & addr_map_i[i].addr);
end
end
// Match the default slave rule
// An input address set is fully contained in a rule's address set if there is a
// match (dec_valid_o) and there are no masked bits in the input address set which
// are not masked also in the rule's address set.
// If the input address set is not fully contained in the union of all rules'
// address sets, forward to default slave.
if (en_default_idx_i)
select_o[default_idx_i.idx] = (!dec_valid_o || |(mask_i & ~default_idx_i.mask));
end

// Assumptions and assertions
Expand All @@ -132,18 +173,37 @@ module multiaddr_decode #(
end

// These following assumptions check the validity of the address map.
// check_idx: Enforces a valid index in the rule.
always @(addr_map_i) #0 begin : proc_check_addr_map
// check_default_idx: Enforces a valid default idx.
// check_rule_idx: Enforces a valid index in the rule.
// check_rule_idx_default: Checks that no rule contains the default index.
always @(addr_map_i, en_default_idx_i, default_idx_i) #0 begin : proc_check_addr_map
if (!$isunknown(addr_map_i)) begin
if (en_default_idx_i) begin
check_default_idx : assume (default_idx_i.idx < NoIndices) else
$fatal(1, $sformatf("Default index value is not allowed!!!\n\
IDX: %h\n\
MAX_IDX: %h\n\
#####################################################",
default_idx_i.idx, (NoIndices-1)));
end
for (int unsigned i = 0; i < NoRules; i++) begin
// check the SLV ids
check_idx : assume (addr_map_i[i].idx < NoIndices) else
check_rule_idx : assume (addr_map_i[i].idx < NoIndices) else
$fatal(1, $sformatf("This rule has a IDX that is not allowed!!!\n\
Violating rule %d.\n\
Rule> IDX: %h\n\
Rule> MAX_IDX: %h\n\
#####################################################",
i, addr_map_i[i].idx, (NoIndices-1)));
if (en_default_idx_i) begin
check_rule_idx_default : assume (addr_map_i[i].idx != default_idx_i.idx) else
$fatal(1, $sformatf("This rule has a IDX that is not allowed!!!\n\
Violating rule %d.\n\
Index: %h\n\
Default index> : %h\n\
#####################################################",
i, addr_map_i[i].idx, default_idx_i.idx));
end
end
end
end
Expand Down

0 comments on commit 0fd2ba3

Please sign in to comment.