Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added function call design #119

Merged
merged 21 commits into from
Sep 12, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions design/func_call/func_call.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Function Calls
WorldofKerry marked this conversation as resolved.
Show resolved Hide resolved

```python
@verilogify(write=True, overwrite=True, optimization_level=1)
def hrange(base, limit, step):
i = base
while i < limit:
yield i
i += step


@verilogify(write=True, overwrite=True, optimization_level=1)
def dup_range(base, limit, step):
inst = hrange(base, limit, step) # 1
for value in inst: # 2
yield value # 3
yield value + 1 # 4
```

```cpp
// ...
hrange _inst(
.base(_hrange_inst_base),
.limit(_hrange_inst_limit),
.step(_hrange_inst_step),
._0(_hrange_inst__0),
._ready(_hrange_inst__ready),
// ...
)
// ...
case (_state) begin
_state_1: begin
_hrange_inst_base <= _base;
_hrange_inst_limit <= _limit;
_hrange_inst_base <= _step;
_hrange_inst__start <= 1;
_hrange_inst__ready <= 0; // optimizer pass can set this to 1
_state <= _state_2;
end
_state_2: begin
_hrange_inst__ready <= 1;
if (_hrange_inst__ready && _hrange_inst__valid) begin
_value <= _hrange_inst__0;
_state <= _state_3;
_hrange_inst__ready <= 0;
end
if (_hrange_inst__done) begin
_state <= _state_done;
_hrange_inst__ready <= 0;
end
end
_state_3: begin
valid <= 1;
_0 <= value;
_state <= _state_4;
end
_state_4: begin
valid <= 1;
_0 <= value + 1;
_state <= _state_2;
end
_state_done: // ...
end
// ...
```
78 changes: 52 additions & 26 deletions design/func_call/hrange.sv
Original file line number Diff line number Diff line change
@@ -1,48 +1,74 @@
/*

# Python Function
@verilogify(write=True, overwrite=True, optimization_level=1)
def hrange(base, limit, step):
i = base
while i < limit:
yield i
i += step


# Test Cases
print(list(hrange(*(0, 10, 2))))

*/

module hrange (
// Function parameters:
input wire signed [31:0] base,
input wire signed [31:0] limit,
input wire signed [31:0] step,
input wire _clock,
input wire _reset,

input wire _clock, // clock for sync
input wire _reset, // set high to reset, i.e. done will be high
Haxrox marked this conversation as resolved.
Show resolved Hide resolved
input wire _start, // set high to capture inputs (in same cycle) and start generating
input wire _wait, // set high to have module pause outputting
output reg _ready, // is high if module done outputting

// Implements a ready/valid handshake based on
// http://www.cjdrake.com/readyvalid-protocol-primer.html
input wire _ready, // set high when caller is ready for output
output reg _valid, // is high if output is valid

output reg _done, // is high if module done outputting

// Output values as a tuple with respective index(es)
output reg signed [31:0] _0
Haxrox marked this conversation as resolved.
Show resolved Hide resolved
);
localparam _state_1 = 0;
localparam _state_0_while_0 = 1;
localparam _statelmaoready = 2;
localparam _statelmaoready = 1;
WorldofKerry marked this conversation as resolved.
Show resolved Hide resolved
localparam _state_0_while_0 = 2;
// Global variables
reg signed [31:0] _i;
reg signed [31:0] _state;
reg signed [31:0] _base;
reg signed [31:0] _limit;
reg signed [31:0] _step;
always @(posedge _clock) begin
_valid <= 0;
_ready <= 0;
_0 <= $signed(0);

_done <= 0;
if (_ready) begin
_0 <= $signed(0);
_valid <= 0;
end
// Start signal takes precedence over reset
if (_reset) begin
_state <= _statelmaoready;
end

if (!(_wait)) begin
if (_start) begin
_base <= base;
_limit <= limit;
_step <= step;
_i <= base;
if ((base < limit)) begin
_0 <= base;
_valid <= 1;
_state <= _state_0_while_0;
end else begin
_ready <= 1;
_state <= _statelmaoready;
end
if (_start) begin
_base <= base;
_limit <= limit;
_step <= step;
_i <= base;
if ((base < limit)) begin
_0 <= base;
_valid <= 1;
_state <= _state_0_while_0;
end else begin
_done <= 1;
_state <= _statelmaoready;
end
end else begin
// If ready or not valid, then continue computation
if ($signed(_ready || !(_valid))) begin
WorldofKerry marked this conversation as resolved.
Show resolved Hide resolved
case (_state)
_state_0_while_0: begin
_i <= $signed(_i + _step);
Expand All @@ -51,7 +77,7 @@ module hrange (
_valid <= 1;
_state <= _state_0_while_0;
end else begin
_ready <= 1;
_done <= 1;
_state <= _statelmaoready;
end
end
Expand Down
29 changes: 14 additions & 15 deletions design/func_call/hrange_tb.sv
Original file line number Diff line number Diff line change
Expand Up @@ -3,52 +3,51 @@ module hrange_tb (
reg _clock;
reg _start;
reg _reset;
reg _wait;
reg _ready;
reg signed [31:0] base;
reg signed [31:0] limit;
reg signed [31:0] step;
wire _ready;
wire _done;
wire _valid;
wire signed [31:0] _0;
hrange DUT (
._clock(_clock),
._start(_start),
._reset(_reset),
._wait(_wait),
._ready(_ready),
.base(base),
.limit(limit),
.step(step),
._ready(_ready),
._done(_done),
._valid(_valid),
._0(_0)
);
always #5 _clock = !_clock;
initial begin
_clock = 0;
_start = 0;
_wait = 0;
_ready = 1;
_reset = 1;
@(negedge _clock);
_reset = 0;

// ============ Test Case 0 with arguments (0, 10, 2) ============
Haxrox marked this conversation as resolved.
Show resolved Hide resolved
base = $signed(0);
limit = $signed(10);
step = $signed(2);
_start = 1;

@(negedge _clock);
base = 'x; // only need inputs at start
limit = 'x; // only need inputs at start
step = 'x; // only need inputs at start
base = 'x; // only need inputs when start is set
Haxrox marked this conversation as resolved.
Show resolved Hide resolved
limit = 'x; // only need inputs when start is set
step = 'x; // only need inputs when start is set
_start = 0;

while (!(_ready)) begin
$display("%0d, %0d", _valid, _0);
while (!(_done)) begin
// `if (_ready && _valid)` also works as a conditional
if (_ready) begin
$display("%0d, %0d, %0d", _valid, _ready, _0);
end
@(negedge _clock);
end
$display("%0d, %0d", _valid, _0);

$display("%0d, %0d, %0d", _valid, _ready, _0);
$finish;
end
endmodule