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

pull request to a new branch #1

Open
wants to merge 48 commits into
base: mastesr
Choose a base branch
from
Open

pull request to a new branch #1

wants to merge 48 commits into from

Conversation

hercule-karuha
Copy link
Owner

No description provided.

bulesim-rlib/Cargo.lock Outdated Show resolved Hide resolved
bulesim-rlib/src/lib.rs Outdated Show resolved Hide resolved
examples/ten_stage_analysis/src/main.rs Show resolved Hide resolved
probe-blue/RProbe.bsv Outdated Show resolved Hide resolved
rb_link/src/lib.rs Outdated Show resolved Hide resolved
rb_link/src/lib.rs Outdated Show resolved Hide resolved
rb_link/src/lib.rs Outdated Show resolved Hide resolved
examples/ten_stage_analysis/src/main.rs Show resolved Hide resolved
bulesim-rlib/src/lib.rs Outdated Show resolved Hide resolved
rb_link/src/test.rs Outdated Show resolved Hide resolved
@hercule-karuha
Copy link
Owner Author

@myrfy001 all fixed

}

/// Read the earliest cycle messages sent by the probes labeled as "fifo" and "fired", and organize them into a PipeLineState.
pub fn get_pipeline_state(&mut self) -> PipeLineState {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the purpose of the Server module? From the name, we think that it should be a module that handles connections, e.g., accept connection, retry connection. But what does the server do after receive a packet should not be included in a module called Server. And maybe there will be many different processing logics, should we put all thoes new logics into the Server module? This is a bad smell in code. Use some design pattern to refactor this.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

// let probe_infos = self.probe_infos.clone();
let b2r_cache = self.b2r_cache.clone();
let r2b_cache = self.r2b_cache.clone();
thread::spawn(move || {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When will this thread terminated? what will happen if this thread terminated?

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

README.md Outdated
$ cd <your bsv projest path>
// add the .a file after the link command
$ <your link command> ../../bluesim-rlib/target/debug/libblue.a

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should have a runable command line, maybe the user doesn't known how to link a .a file to their bluespec simulator. After all, linking a library to simulator is not a normal operation. bluespec also doesn't have much doc about it.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

panic!("cycles over flow!");
}
let mut stream = STREAM.get_or_init(|| {
UnixStream::connect(String::from("/tmp/b2rr2b")).expect("Failed to connect to socket")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In fact, .expect and .unwrap is almost the same. Both of them will panic the process. Rust use Result to handle errors, so, what's your idea not to use Result to handle errors?

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Beacuse i just don't think the errors are recoverable.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think all examples should have a build script as a playground. It can be a make file or a rust build.rs. No matter which way, we should let the user run the demos using a single command line like 'make'. The example should show the users how to build bsv, how to build probe library, how to link them together, hou to run the upper app to use those probes.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

panic!("cycles over flow!");
}
let mut stream = STREAM.get_or_init(|| {
UnixStream::connect(String::from("/tmp/b2rr2b")).expect("Failed to connect to socket")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to speed up test, it's common to run multi test process at the same time. A hardcoded local unix-stream will not work when there is multi process running different tests.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed


(* synthesize *)
module mkAdderPipeline(Empty);
function gen_fire_probes(Integer x) = mkRProbe(fromInteger(x + 10));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what does those magic numbers mean?

don't use magic numbers, even in testcases or examples.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed


(* synthesize *)
module mkAdderPipeline(Empty);
function gen_fire_probes(Integer x) = mkRProbe(fromInteger(x + 10));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

by the way, is it possible to use a string as the probe id to make it more meaningful?

b2r_cache: Arc::new(Mutex::new(HashMap::new())),
r2b_cache: Arc::new(Mutex::new(HashMap::new())),
}
}

/// Start a thread to run the server.
/// Create a UnixListener at "/tmp/b2rr2b".

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment is outdated

@@ -24,7 +25,11 @@ pub unsafe extern "C" fn get(res_ptr: *mut u8, id: u32, _cycles: u32, size: u32)
panic!("cycles over flow!");
}
let mut stream = STREAM.get_or_init(|| {
UnixStream::connect(String::from("/tmp/b2rr2b")).expect("Failed to connect to socket")
let socket = match env::var("B2R_SOCKET") {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

duplicated code should go into a function

@@ -40,6 +42,7 @@ module mkAdderPipeline(Empty);
probe.put_data(data + 1);
put_times <= put_times + 1;
if(put_times == 9) begin
probe.shut_down_server();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No parentheses here

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

two makefile has a lot in common, can you extract some common part to a seperate file and include them? Suppose you will have many makefile in the future, once you need to change something, you won't need to change every file.


impl B2RServer {
/// make a new server with socket: /tmp/b2rr2b
pub fn new() -> Self {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this API should be removed

endmethod
endmodule

module mkFIFOFProbe#(Bit#(WORD_WIDTH) id, FIFOF#(t) fifo)(Empty);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since some id is kept for internal use(e.g., control shutdown), you should check if the user supplied id is conflict with those reserved ids.

/// Cache bidirectional data and send data upon receiving requests.
pub struct B2RServer {
socket_path: String,
b2r_cache: Arc<Mutex<HashMap<u32, VecDeque<B2RMessage>>>>,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the simulation run a long time, will this buffer overflow or lead to OOM?

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The getter poped from the cache, i think the message shouldn't wait too long to be processed in debug program.
So I think it won't lead to OOM.

@myrfy001
Copy link

After looking into your implement detail, I found that it seems this framework is a offline-analyse framework. But it should also work in a online-analyse style, that is, you can inject data to simulator on the fly, and analyse simulator state on the fly. For example, some probe can be used as a trigger (you can think it as a conditional breakpoint in software debugger), like when some probe's value is True, or some probes' value do AND logic operation and the result is True, then block the simulator and print some mesage.

So, to implement this behivour, the framework shoud be event driven, and you can hook some analyse logic by subscribe to the events.

By the way, the offline analyse is also another way to do debug and it can also be kept.

@hercule-karuha
Copy link
Owner Author

@myrfy001 fixed

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We must treat naming seriously. For the name config, it means something that can be tuned. But thoes two things here seems not. Maybe this file should be called consts.rs or something else?

socket_path: String,
running: Arc<AtomicBool>,
cycle: Arc<AtomicU32>,
b2r_cache: Arc<Mutex<HashMap<u32, VecDeque<B2RMessage>>>>,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not use a channel to do cross thread communication? What you did here is almost build a channel by hand and make code verbose.

}

/// Get all message send by the probe with id.
pub fn get_id_all(&mut self, id: u32) -> Vec<B2RMessage> {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

again, naming!
get_id_all means get all IDs, but this method returns messages instead of IDs.

use std::sync::{Arc, Mutex};

/// A getter to get message from the bluesim by id
pub struct IDGetter {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Naming problem again.


/// Get all the messages sent by the earliest cycle.
/// If there are no messages available, it will return an empty Vec.
pub fn get_cycle_message(&mut self) -> Vec<B2RMessage> {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

naming problem. Why the important "earliest" not show in the method name but show in the comment?

let mut b2r_cache: std::sync::MutexGuard<HashMap<u32, VecDeque<B2RMessage>>> =
self.b2r_cache.lock().expect("Fail to lock b2r_cache");

for fifo_id in &self.fifos {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this can be rewrite in rust style using min instead of for loop?

// the fifo message len must be 2
assert_eq!(first_message.message.len(), 2);
let b2r_message = messages.pop_front().expect("front error");
if b2r_message.message[0] == 0 {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No magic number here. You should define a struct to represent this kind of message, which has two fields, one for empty and one for full.

If this is a really big project, or message type boost in the future, it will be hard to remember the meaning of each byte index.

/// fire_fules: the fired rules
pub struct PipeLineState {
pub cycle: u32,
pub full_fifos: Vec<u32>,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe you should define a new type called ProbeID as u32?

And also, if it stores IDs, then you should show it. Otherwise, when someone read code somewhere else in the code base, and see a struct called full_fifos, since there is a s, he can known this field is a Vec or a slice like things. But what is in this slice? He may think they are some struct represent a FIFO object, and won't think they are IDs.


impl B2RPublisher {
/// Creates a new B2RPublisher instance with the specified socket path.
pub fn new_with(path: &str) -> Self {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does this module works with other modules? It will take the unix stream. What if I want to use b2r_cache and r2b_cache while also using Subscriber framework?
As a framework, different part should be able to be used together, not splited.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants